<?php

namespace App\Models;

use App\Constant\Constant;
use App\Constant\ConstantMap;
use App\Models\Scopes\CreateAtDesc;
use App\Models\Scopes\SortAsc;

/**
 * App\Models\AdminMenu
 *
 * @property int $id
 * @property string $menu_no 编码
 * @property string $name 名称
 * @property string $class_name 按钮类名
 * @property int $pid 上级ID
 * @property int $level 等级
 * @property int $type 类型：1菜单 2操作按钮
 * @property int $is_win 是否为窗口菜单：1是 0否
 * @property string $icon 图标
 * @property string $uri 路由
 * @property int $sort 排序，越小越靠前
 * @property int $btn_type 按钮类型：1普通操作 2查询 3导出 4弹窗 5保存
 * @property int $is_delete 是否删除：1是 0否
 * @property string $path_text
 * @property array $path
 * @property int $is_export 是否导出：1是 0否
 * @property \Illuminate\Support\Carbon $created_at
 * @property \Illuminate\Support\Carbon $updated_at
 * @property-read \Illuminate\Database\Eloquent\Collection<int, AdminMenu> $children
 * @property-read int|null $children_count
 * @property-read mixed $btn_ftype
 * @property-read mixed $ftype
 * @method static \Illuminate\Database\Eloquent\Builder|AdminMenu newModelQuery()
 * @method static \Illuminate\Database\Eloquent\Builder|AdminMenu newQuery()
 * @method static \Illuminate\Database\Eloquent\Builder|BaseModel paramsQuery($fields, $params = [])
 * @method static \Illuminate\Database\Eloquent\Builder|AdminMenu query()
 * @method static \Illuminate\Database\Eloquent\Builder|AdminMenu whereBtnType($value)
 * @method static \Illuminate\Database\Eloquent\Builder|AdminMenu whereClassName($value)
 * @method static \Illuminate\Database\Eloquent\Builder|AdminMenu whereCreatedAt($value)
 * @method static \Illuminate\Database\Eloquent\Builder|AdminMenu whereIcon($value)
 * @method static \Illuminate\Database\Eloquent\Builder|AdminMenu whereId($value)
 * @method static \Illuminate\Database\Eloquent\Builder|BaseModel whereIds($ids = [])
 * @method static \Illuminate\Database\Eloquent\Builder|AdminMenu whereIsDelete($value)
 * @method static \Illuminate\Database\Eloquent\Builder|AdminMenu whereIsExport($value)
 * @method static \Illuminate\Database\Eloquent\Builder|AdminMenu whereIsWin($value)
 * @method static \Illuminate\Database\Eloquent\Builder|AdminMenu whereLevel($value)
 * @method static \Illuminate\Database\Eloquent\Builder|AdminMenu whereMenuNo($value)
 * @method static \Illuminate\Database\Eloquent\Builder|AdminMenu whereName($value)
 * @method static \Illuminate\Database\Eloquent\Builder|AdminMenu wherePath($value)
 * @method static \Illuminate\Database\Eloquent\Builder|AdminMenu wherePathText($value)
 * @method static \Illuminate\Database\Eloquent\Builder|AdminMenu wherePid($value)
 * @method static \Illuminate\Database\Eloquent\Builder|AdminMenu whereSort($value)
 * @method static \Illuminate\Database\Eloquent\Builder|AdminMenu whereType($value)
 * @method static \Illuminate\Database\Eloquent\Builder|AdminMenu whereUpdatedAt($value)
 * @method static \Illuminate\Database\Eloquent\Builder|AdminMenu whereUri($value)
 * @mixin \Eloquent
 */
class AdminMenu extends BaseModel
{
    protected $table = 'admin_menus';

    protected $casts = [
      'path' => 'array',
    ];

    public static function boot()
    {
        self::addGlobalScope(new SortAsc());

        parent::boot(); // TODO: Change the autogenerated stub

        self::saved(function ($model) {
            /** @var self $model */
            if ($model->isDirty('pid') || $model->name) {
                if ($model->pid) {
                    $parent_path   = self::whereId($model->pid)->first()->path;
                    $parent_path[] = $model->id;
                } else {
                    $parent_path = [$model->id];
                }
                $path_text = '';
                if (count($parent_path)) {
                    $path_text = self::withoutGlobalScope(new SortAsc())->withoutGlobalScope(new CreateAtDesc())->whereIds($parent_path)->pluck('name')->toArray();
                    $path_text = implode('/', $path_text);
                }
                self::whereId($model->id)->update(['path' => json_encode(array_map('intval', $parent_path)), 'path_text' => $path_text]);

                // 修改子集
                $children = self::withoutGlobalScope(new CreateAtDesc())->withoutGlobalScope(new SortAsc())
                    ->whereJsonContains('path', "[$model->id]")
                    ->where('id', '<>', $model->id)
                    ->get();
                foreach ($children as $child) {
                    $parent = $child->parent;
                    if ($parent) {
                        $path   = $parent->path;
                        $path[] = $child->id;
                        $temp   = [
                            'path'      => json_encode($path),
                            'path_text' => $parent->path_text . '/' . $child->name
                        ];
                        self::whereId($child->id)->update($temp);
                    }
                }
            }
        });
    }

    public function getFtypeAttribute()
    {
        return ConstantMap::$menuTypeMap[$this->type] ?? "";
    }

    public function getBtnFtypeAttribute()
    {
        return ConstantMap::$btnTypeMap[$this->btn_type] ?? "";
    }

    public static function getForms($fields = [])
    {
        $routes      = collect(\Route::getRoutes())->pluck('uri')->toArray();
        $routes_data = [];
        foreach ($routes as $route) {
            $routes_data[] = [
                'value' => '/' . $route,
                'label' => '/' . $route
            ];
        }
        $pids  = self::whereType(Constant::MenuType_Default)->select(['id', 'name', 'pid'])->get();
        $pids  = array_to_tree(json_decode(json_encode($pids), true), 'id', 'pid', 'children');
        $forms = [
            'pid'       => ['title' => '上级资源', 'type' => 'treeSelect', 'options' => $pids],
            'name'      => ['title' => '名称', 'type' => 'text'],
            'menu_no'   => ['title' => '权限码', 'type' => 'text'],
            'type'      => ['title' => '资源类型', 'type' => 'select', 'options' => map_to_options(ConstantMap::$menuTypeMap)],
            'btn_type'  => ['title' => '按钮类型', 'type' => 'select', 'options' => map_to_options(ConstantMap::$btnTypeMap)],
            'is_export' => ['title' => '是否可导出', 'type' => 'select', 'options' => map_to_options(ConstantMap::$yesOrNoMap)],
            'icon'      => ['title' => '图标', 'type' => 'text'],
            'class_name' => ['title' => '按钮样式', 'type' => 'text'],
            'uri'       => ['title' => '路由', 'type' => 'select', 'options' => $routes_data],
            'sort'      => ['title' => '排序', 'type' => 'number'],
        ];
        $data  = [];
        foreach ($fields as $field) {
            if (isset($forms[$field])) {
                $data[$field]          = $forms[$field];
                $data[$field]['field'] = $field;
            }
        }
        return $data;
    }

    public function children()
    {
        return $this->hasMany(self::class, 'pid', 'id');
    }
}
